home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS16.ADF
/
C
/
FileZap3
/
FileZap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-27
|
12KB
|
414 lines
/* FileZAP.c : (c) 1986 John Hodgson
FileZAP provides a disk-based file zap utility as popularized
on TRS systems. Although tested, the author cannot be held liable
for incidental or consequential damage incurred through the use
of this program.
Special attention was paid to correct and proper EOF handling;
please notify the author of any discrepancies (cursor movement
errors, file growth and/or shrinkage)
Note : Although the physical length of Amiga sectors is just short
of 512 bytes, 256 byte records are the longest ones that can be
displayed nicely on a 80x24 screen with all pertinent information.
Have fun! Let's help make this world free from protected disks!
John Hodgson
P.O. Box 1643
Pebble Beach, Ca. 93953
*/
/* Revision History
Rev 3.0 : Added new console I/O, causing smaller code, faster
speed, and a much cleaner (UNIX style) program. jec
Rev 2.4 : A few extra changes. jec
Rev 2.3 : Screen cursor changed for better legibility, also
several routines optimized for speed. jec
Rev 2.2 : Certain portability problems resolved for Aztec "C"
*/
#include "fcntl.h"
#include "exec/types.h"
#include "intuition/intuition.h"
#define getchar mygetc
#define putchar myputc
#define puts myputs
#define printf myprintf
#define exit myexit
#define CR 13
#define EOF 0
#define ERROR -1
#define HEX 0
#define ASC 1
char WindowTitle[] = "FileZap Ver 3.0 by John Hodgson & Jim Cooper";
/* record buffer physical cursor position (0-15 rows x 0-15 cols) */
int phycurx=0,phycury=0;
/* physical x-position to video x-cursor map table */
int posconv[16]={ 6,8,10,12,15,17,19,21,24,26,28,30,33,35,37,39 };
void error(str, arg)
char *str, *arg;
{
int len;
char strbuf[80];
len = sprintf(&strbuf[0],str,arg);
prstr((80-len)/2+1,10,strbuf);
prstr(25,12,"(Press any key to exit)\n");
len = getchar();
}
main(argc,argv)
int argc;
char *argv[];
{
unsigned char inkey,prevchar,secbuf[256];
int rdfp,status,lastrec,curec,shiftnum,eof,col;
long lseek();
if (argc!=2) {
error("\x9B33mUsage :\x9B31m %s <filename>\n", argv[0]);
exit(0x55);
}
if ((rdfp=open(argv[1],O_RDWR))==ERROR) {
error("\x9B33mError opening file\x9B31m %s\n",argv[1]);
exit(0x4F);
}
curec=1; shiftnum=0;
lastrec=(lseek(rdfp,-1L,2)/256)+1; /* compute last record #, 1..n */
/* compute EOF remainder by reading from last record */
lseek(rdfp,(long)((lastrec-1)*256),0); eof=read(rdfp,&secbuf[0],256);
/* All data gathered, read 1st record */
lseek(rdfp,0L,0); status=read(rdfp,&secbuf[0],256);
for (col=0;col<=0xf0;col+=0x10)
printf("%02X : \n", col);
prstr(62,1,"Cur rec :");
prstr(62,2,"End rec :");
prstr(62,3,"Offset :");
locate(62,5);
printf("EOF : %d",eof+((lastrec-1)*256)-1);
prstr(62,9,"Loc : ");
prstr(8,18,"COMMANDS : S) Starting record E) Ending record");
prstr(8,19," F) Forward record B) Backward record");
prstr(8,20," U) Update record R) Recover record");
prstr(8,21," <SPACE> Enter HEX modify *) Enter ASCII modify");
prstr(8,22," <n>CR Goto record n ^C Exit program");
locate(1,23);
printf("File : %s", argv[1]);
display_record(&secbuf[0],curec,lastrec,status);
movecur(&secbuf[0],0,0,status); /* display initial cursor */
show_offset(curec); /* show offset into file */
prevchar='\0'; /* zero previous char (used for escape checks) */
do {
inkey = getchar(); /* synchronous kybd scan */
if (prevchar==0x9b) { /* Give 2-byte CSI sequences priority (arrows) */
prevchar='\0';
switch(inkey) {
case 'A':
movecur(&secbuf[0],0,-1,status);
show_offset(curec);
break;
case 'B':
movecur(&secbuf[0],0,1,status);
show_offset(curec);
break;
case 'C':
movecur(&secbuf[0],1,0,status);
show_offset(curec);
break;
case 'D':
movecur(&secbuf[0],-1,0,status);
show_offset(curec);
break;
}
continue; /* no point in further tests, restart */
}
inkey=toupper(inkey); /* force UC for testing */
/* "Goto" record handling - buffer all digits into a shift
register until too large, or non-digit pressed */
if (isdigit(inkey)) shiftnum=shiftnum*10+inkey-'0';
else
if (inkey!=CR) shiftnum=0;
if (shiftnum>lastrec) shiftnum=0;
if ((inkey==13) && (shiftnum>0)) { /* Goto */
lseek(rdfp,(long)(256*(shiftnum-1)),0);
status=read(rdfp,&secbuf[0],256);
curec=shiftnum; shiftnum=0;
display_record(&secbuf[0],curec,lastrec,status);
phycurx=phycury=0; movecur(&secbuf[0],0,0,status);
show_offset(curec);
}
if ((inkey=='F') && (curec<lastrec)) { /* Forward record */
status=read(rdfp,&secbuf[0],256);
++curec;
display_record(&secbuf[0],curec,lastrec,status);
phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
show_offset(curec);
}
if ((inkey=='B') && (curec>1)) { /* Backward record */
--curec;
lseek(rdfp,(long)((curec-1)*256),0);
status=read(rdfp,&secbuf[0],256);
display_record(&secbuf[0],curec,lastrec,status);
phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
show_offset(curec);
}
switch(inkey) {
case 'R': /* Restore (unmodified) record */
lseek(rdfp,(long)((curec-1)*256),0);
status=read(rdfp,&secbuf[0],256);
display_record(&secbuf[0],curec,lastrec,status);
phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
show_offset(curec);
break;
case 'S': /* Rewind */
curec=1;
lseek(rdfp,0L,0);
status=read(rdfp,&secbuf[0],256);
display_record(&secbuf[0],curec,lastrec,status);
phycurx=phycury=0;movecur(&secbuf[0],0,0,eof);
show_offset(curec);
break;
case 'U': /* Update (save modified) record */
lseek(rdfp,(long)-status,1);
write(rdfp,&secbuf[0],status);
DisplayBeep(NULL);
break;
case 'E': /* skip to Ending record */
curec=lastrec;
lseek(rdfp,(long)(curec-1)*256,0);
status=read(rdfp,&secbuf[0],256);
display_record(&secbuf[0],curec,lastrec,status);
phycurx=phycury=0;movecur(&secbuf[0],0,0,status);
show_offset(curec);
break;
case ' ': /* Enter hex-modify mode */
edit_window(curec,&secbuf[0],status,HEX);
break;
case '*': /* Enter ascii-modify mode */
edit_window(curec,&secbuf[0],status,ASC);
break;
}
prevchar=inkey; /* update previous char for CSI sequence checks */
}
while (inkey!=3); /* loop until CTRL-C */
close(rdfp); exit(0); /* cleanup & exit */
}
display_record(secbuf,curec,finsec,eof)
int curec,finsec,eof;
char secbuf[16][16];
{
int row,col,i;
char strbuf[100],*kludge;
/* kludge maps 2-d array to 1-d so we can more easily
fill incomplete records w/dummy chars past EOF */
kludge=&secbuf[0][0];
for (i=256;i>eof;--i) kludge[i-1]='#';
/* EOL's included below to erase old values */
locate(72,1); printf("\x9bK%d",curec);
locate(72,2); printf("\x9bK%d",finsec);
/* record display core routine : Due to the slowness of the
console file drivers, display is line buffered for speed. */
for (row=0;row<=15;row++) {
i=0;
for (col=0;col<=15;col++) {
hexconv(&strbuf[i],secbuf[row][col]); i+=2;
if (((col+1)%4)==0) strbuf[i++]=' ';
}
strbuf[i++]=':'; strbuf[i++]=' ';
for (col=0;col<=15;col++) strbuf[i++]=valid_display(secbuf[row][col]);
strbuf[i]='\0'; prstr(6,row+1,strbuf);
}
}
locate(x,y) /* move cursor to x,y */
int x,y;
{
/* complete escape sequence for cursor pos is :
<CSI><row><;><col><H> where CSI is 9BH. */
printf("\x9b%c%c;%c%cH",(y/10+48),((y%10)+48),(x/10+48),((x%10)+48));
}
hexconv(result,byte) /* byte to 2 ASCII hex digits */
unsigned char result[2],byte;
{
result[0]=(byte>>4)+48+7*((byte>>4)>9);
result[1]=(byte & 0xf)+48+7*((byte & 0xf)>9);
}
prstr(posx,posy,string) /* "Print-At" routine */
int posx,posy;
char *string;
{
locate(posx,posy);
printf("%s", string);
}
movecur(secbuf,deltax,deltay,eof) /* move cursor & update display */
int deltax,deltay,eof;
char secbuf[16][16];
{
/* update ASCII side */
locate(phycurx+44,phycury+1);
printf("%c", valid_display(secbuf[phycury][phycurx]));
/* disallow cursor movement past EOF */
if (fixpos(eof,deltax,deltay,secbuf)) return(0);
locate(68,9);
printf("%02X", phycury*16+phycurx); /* update LOC value */
locate(phycurx+44,phycury+1);
printf("\x9b33m%c\x9b31m", valid_display(secbuf[phycury][phycurx]));
locate(posconv[phycurx],phycury+1); /* update HEX ("real") cursor */
}
show_offset(curec)
int curec;
{
locate(72,3);
printf("\x9bK%d", ((curec-1)*256)+(phycury*16)+phycurx);
locate(posconv[phycurx],phycury+1); /* update HEX ("real") cursor */
}
edit_window(curec,secbuf,eof,hex) /* record edit routine */
int curec,eof,hex;
char secbuf[16][16];
{
char ascii,lsb,msb;
int status=NULL,tempx;
if (hex==HEX) prstr(62,11,"\x9bKModify : HEX");
else prstr(62,11,"\x9bKModify : ASCII");
prstr(62,12,"<ESC> to exit");
do {
locate(posconv[phycurx],phycury+1); /* cursor over hex digits */
printf("\x9b33m%02X\x9b31m", secbuf[phycury][phycurx]&255);
locate(posconv[phycurx],phycury+1); /* restore cursor */
if (hex==HEX) { /* hex-modify : Actually, any invalid char exits */
if ((msb=hexfetch())==FALSE) { status=1; goto exit; }
putchar(msb); /* print msb */
if ((lsb=hexfetch())==FALSE) { status=1; goto exit; }
putchar(lsb); /* print lsb */
if (msb>'9') msb-=55; else msb-='0'; /* hex to binary */
if (lsb>'9') lsb-=55; else lsb-='0';
secbuf[phycury][phycurx]=(msb<<4)+lsb; /* update buffer */
}
else { /* ASCII-modify */
ascii = getchar(); /* fetch ASCII char from user */
if (ascii==0x1b) { status=1; goto exit; }/* exit on <ESC> */
secbuf[phycury][phycurx]=ascii; /* update buffer */
}
exit:
locate(posconv[phycurx],phycury+1); /* restore cursor */
printf("%02X", secbuf[phycury][phycurx]&255);
movecur(&secbuf[0],0,0,eof); /* update ASCII side */
show_offset(curec);
if (status==1) break; /* don't move cursor if <ESC> */
tempx=phycurx; /* save previous x-coord */
movecur(&secbuf[0],1,0,eof); /* move to next digit */
show_offset(curec);
if (tempx==phycurx) status=1; /* cancel modify if blocked */
}
while (status==NULL); /* edit until exit */
prstr(62,11,"\x9bK"); /* erase info msgs */
prstr(62,12,"\x9bK");
locate(posconv[phycurx],phycury+1); /* restore cursor B4 exit */
}
hexfetch() /* Fetch valid ascii HEX sequence from user */
{
unsigned char nybble;
for (;;) {
nybble = getchar();
if (nybble==0x1b) return(FALSE);
if (!isalnum(nybble)) continue;
nybble=toupper(nybble);
if (nybble>'F') continue;
return (int)nybble;
}
}
fixpos(eof,deltax,deltay,secbuf) /* cursor bounds check routine */
int eof,deltax,deltay;
char secbuf[16][16];
{
int tempx,tempy;
tempx=phycurx+deltax; tempy=phycury+deltay;
if (tempx>15) { tempy++; tempx=0; } /* cursor screen-wrap code */
if (tempy>15) tempy=0;
if (tempx<0) { tempx=15; tempy--; }
if (tempy<0) tempy=15;
if ((((tempy)*16) + (tempx)) > eof-1) { /* cleanup & exit if past EOF */
locate(phycurx+44,phycury+1); /* update ASCII cursor */
printf("\x9b33m%c\x9b31m", valid_display(secbuf[phycury][phycurx]));
locate(posconv[phycurx],phycury+1); /* redraw HEX cursor */
DisplayBeep(NULL); /* Flash user so he wakes up */
return(TRUE); /* and exit */
}
phycurx=tempx; phycury=tempy; /* Otherwise, update global cursor */
return(FALSE);
}
valid_display(byte) /* return filtered ASCII char */
char byte;
/* Filter all CTRL & CSI chars which could mess things up */
{
if ((byte>31) && (byte!=0x9b)) return(int)byte;
else return(int)'.';
}